﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////


#include "GnufColorParameterDisplay.h"
#include "GnufParameterDisplayCustomFactory.h"
#include "GcmpBuiltInParameterDefinitions.h"
#include "GnufColorControl.h"
#include "GnufColorInputControl.h"
#include "GnufInfo.h"
#include "GnufItem.h"
#include "GnufNameValuePairs.h"
#include "IDocument.h"
#include "IElement.h"
#include "IElementParameters.h"
#include "IParameter.h"
#include "IParameterDefinitionLibrary.h"
#include "IParameterValueColor.h"
#include "IParameterValueElementId.h"
#include "IParameterValueStorage.h"
#include "FamilyElementUtils.h"
#include "IFamilyFilledRegion.h"
#include "IUserTransaction.h"
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace gcmp;
using namespace gnuf;
using namespace gfam;

const std::wstring ColorParameterDisplay::s_multiTypeText = GBMP_TR(L"                      *多种*"); // 临时方案，为了居中对齐

ColorParameterDisplay::ColorParameterDisplay()
    : m_currentValue(nullptr)
    , m_colorControl(nullptr)
    , m_colorInputControl(nullptr)
{
}

gnuf::Item * ColorParameterDisplay::OnDisplay(gnuf::NameValuePairBlock * pNameValuePairBlock, gcmp::IElement * pElement, int parameterId)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pNameValuePairBlock, L"pNameValuePairBlock为空", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pElement, L"pElement为空", L"paramodel", L"2024-02-20");

    m_elementId = pElement->GetElementId();
    m_pDoc = pElement->GetDocument();
    m_colorControl = GetColorControl(pElement, parameterId, pNameValuePairBlock);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(m_colorControl, L"m_colorControl为空", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(GetParameter(pElement, parameterId), L"GetParameter(pElement, parameterId)为空", L"paramodel", L"2024-02-20");
    gcmp::Color currentColor = GetParameter(pElement, parameterId)->GetValueAsColor();

    IFamilyFilledRegion * pFilledRegion = FamilyElementUtils::CastElement<IFamilyFilledRegion>(pElement);
    if (pFilledRegion)
    {
        m_colorControl->enableSmartColor(pFilledRegion->GetSmartColorMode() == SmartColorMode::SmartAntiBackgroundColor);
    }
    m_colorControl->setColor(currentColor.R, currentColor.G, currentColor.B, currentColor.A);

    m_colorInputControl = NEW_AS_OWNER_PTR(ColorInputControl, this);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(m_colorInputControl, L"m_colorInputControl为空", L"paramodel", L"2024-02-20");
    m_colorInputControl->subscribe(m_colorControl);

    return m_colorControl;
}

gnuf::Item * ColorParameterDisplay::OnDisplay(gnuf::NameValuePairBlock * pNameValuePairBlock, const std::vector<gcmp::IElement*>& elements, int parameterId)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pNameValuePairBlock, L"pNameValuePairBlock为空", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(!elements.empty(), L"elements为空", L"paramodel", L"2024-02-20");
    for (auto one : elements) DBG_WARN_AND_RETURN_NULLPTR_UNLESS(one, L"Empty pointer!", L"paramodel", L"2024-02-20");

    m_colorControl = GetColorControl(elements[0], parameterId, pNameValuePairBlock);

    m_colorInputControl = NEW_AS_OWNER_PTR(ColorInputControl, this);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(m_colorInputControl, L"m_colorInputControl为空", L"paramodel", L"2024-02-20");
    m_colorInputControl->subscribe(m_colorControl);

    return m_colorControl;
}

void ColorParameterDisplay::onColorChanged(std::uint8_t r, std::uint8_t g, std::uint8_t b, std::uint8_t a)
{
    SetCurrentValueStorage(IParameterValueColor::Create(gcmp::Color(r, g, b, a)));
}

void ColorParameterDisplay::onSmartColorEnabled(bool enabled)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_pDoc, L"m_pDoc is nullptr", L"paramodel", L"2024-02-20");
    IElement* pElement = m_pDoc->GetElement(m_elementId);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pElement, L"pElement is nullptr", L"paramodel", L"2024-02-20");

    IFamilyFilledRegion * pFilledRegion = FamilyElementUtils::CastElement<IFamilyFilledRegion>(pElement);
    if (pFilledRegion)
    {
        gcmp::OwnerPtr<IUserTransaction> opTransaction = IUserTransaction::Create(m_pDoc.Get(), L"Smart color transaction");
        DBG_WARN_AND_RETURN_VOID_UNLESS(opTransaction, L"opTransaction为空", L"paramodel", L"2024-02-20");
        pFilledRegion->SetSmartColorMode(enabled ? gcmp::SmartColorMode::SmartAntiBackgroundColor : gcmp::SmartColorMode::Invalid);
        const bool ret = opTransaction->Commit();
        DBG_WARN_AND_RETURN_VOID_UNLESS(ret, L"事务Commit失败", L"paramodel", L"2024-02-20");
    }
}

gcmp::OwnerPtr<gcmp::IParameterValueStorage> ColorParameterDisplay::GetValue(IDocument* pDoc, const std::vector<gcmp::ElementId>& elements, const gnuf::Item* pItem) const
{
    if (nullptr == m_currentValue.get())
        return nullptr;

    return m_currentValue ? m_currentValue->Clone() : IParameterValueElementId::Create(ElementId::InvalidID);
}

gnuf::ColorControl * ColorParameterDisplay::GetColorControl(gcmp::IElement * pElement, int parameterId, gnuf::NameValuePairBlock * pNameValuePairBlock)
{
    IDocument* pDoc = pElement->GetDocument();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空", L"paramodel", L"2024-02-20");
    OwnerPtr<IParameter> opParam = GetParameter(pElement, parameterId);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opParam, L"opParam为空", L"paramodel", L"2024-02-20");
    const IParameterValueStorage* pStorage = opParam->GetParameterValueStorage();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pStorage, L"pStorage为空", L"paramodel", L"2024-02-20");
    SetCurrentValueStorage(pStorage->Clone());

    gnuf::ColorControl* pColorControl = pNameValuePairBlock->addItem<ColorControl>(gnuf::Info(opParam->GetName()));
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pColorControl, L"pColorControl为空", L"paramodel", L"2024-02-20");

    IFamilyFilledRegion * pFilledRegion = FamilyElementUtils::CastElement<IFamilyFilledRegion>(pElement);
    if (pFilledRegion)
    {
        pColorControl->supportSmartColor(true);
    }

    return pColorControl;
}

gcmp::OwnerPtr<gcmp::IParameter> ColorParameterDisplay::GetParameter(gcmp::IElement * pElement, int parameterId)
{
    const IElementParameters* pParameter = pElement->GetElementParameters();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pParameter, L"pParameter为空", L"paramodel", L"2024-02-20");
    return TransferOwnership(pParameter->GetParameterById(parameterId));
}

GnufParameterDisplayCustomCreator s_colorNameParameterDisplayCreator(
    PARAMETER_UID(ColorBuiltInParameter), NEW_AS_OWNER_PTR(ColorParameterDisplay));